package dao

import (
	"context"
	"device-admin/internal/dal"
	"device-admin/internal/models"
	"strings"

	"192.168.1.75/go-pkg/errorx"
	"gorm.io/gen/field"
)

type Device struct{}

// TotalDevice 获取总设备数量
func (ds Device) TotalDevice(
	ctx context.Context,
	query *dal.Query,
	merchantPath string, //商户路径，多个以逗号分隔
	locationID string, // 位置id，多个以逗号分隔
) int {
	var res struct {
		Total int `gorm:"column:total"`
	}
	d := dal.Device
	dg := d.WithContext(ctx)
	tx := d.WithContext(ctx).
		Select(d.ID.Count().As("total")).
		Where(field.NewInt(d.TableName(), d.MerchantID.ColumnName().String()).Gt(1))

	// 所属商户，Group条件
	var tx1 dal.IDeviceDo
	merchantPathArr := strings.Split(merchantPath, ",")
	if len(merchantPathArr) > 0 {
		for index, path := range merchantPathArr {
			if index == 0 {
				tx1 = dg.Where(d.MerchantPath.Like(path + "%"))
			} else {
				tx1.Or(d.MerchantPath.Like(path + "%"))
			}
		}
		tx.Where(tx1)
	}
	if len(locationID) > 0 {
		tx = tx.Where(d.LocationID.In(strings.Split(locationID, ",")...))
	}
	tx.Scan(&res)
	return res.Total
}

// Exists 设备是否存在
func (Device) Exists(ctx context.Context, query *dal.Query, robotID string) bool {
	d := dal.Device
	count, err := d.WithContext(ctx).Where(d.RobotID.Eq(robotID)).Count()
	if err != nil || count < 0 {
		return false
	}
	return true
}

type DeviceDetail struct {
	models.Device
	LocationName      string `gorm:"column:location_name"`
	LocationLatitude  string `gorm:"column:location_latitude"`
	LocationLongitude string `gorm:"column:location_longitude"`
	ProvinceID        string `gorm:"column:province_id"`
	CityID            string `gorm:"column:city_id"`
	DistrictID        string `gorm:"column:district_id"`
	PositionName      string `gorm:"column:position_name"`
}

// Detail 设备详情
func (Device) Detail(ctx context.Context, query *dal.Query, robotID string) (*DeviceDetail, error) {
	details := []*DeviceDetail{}
	d := dal.Device
	l := dal.Location
	d.WithContext(ctx).
		Where(d.RobotID.Eq(robotID)).
		Select(d.ALL, l.Name.As("location_name"), l.Latitude.As("location_latitude"), l.Longitude.As("location_longitude"), l.ProvinceID, l.CityID, l.DistrictID).
		LeftJoin(l, l.ID.EqCol(d.LocationID)).
		Limit(1).
		Scan(&details)
	if len(details) <= 0 {
		return nil, errorx.New("获取设备详情失败", -1)
	}
	return details[0], nil
}

// HasPermissions 是否有设备操作权限
func (Device) HasPermissions(ctx context.Context, query *dal.Query, robotID, userMerchantPath string) bool {
	d := dal.Device
	count, _ := d.WithContext(ctx).
		Where(d.RobotID.Eq(robotID)).
		Where(d.MerchantPath.Like(userMerchantPath + "%")).
		Count()
	return count > 0
}

// SetMerchant 设置设备所属商户
func (Device) SetMerchant(ctx context.Context, query *dal.Query, robotID, merchantID, merchantPath string) (bool, error) {
	d := query.Device
	res, _ := d.WithContext(ctx).
		Where(d.RobotID.Eq(robotID)).
		UpdateSimple(
			d.MerchantID.Value(merchantID),
			d.MerchantPath.Value(merchantPath),
		)
	if res.RowsAffected > 0 {
		return true, nil
	} else {
		return false, errorx.New("设置失败", -2)
	}
}

// ResetLocation 重置设备的位置
func (Device) ResetLocation(ctx context.Context, query *dal.Query, robotID string) {
	d := dal.Device
	d.WithContext(ctx).Where(d.RobotID.Eq(robotID)).UpdateSimple(d.LocationID.Null())
}

// ResetServicePhone 重置服务电话
func (Device) ResetServicePhone(ctx context.Context, query *dal.Query, robotID string) {
	d := dal.Device
	d.WithContext(ctx).Where(d.RobotID.Eq(robotID)).UpdateSimple(d.ServicePhone.Value(""))
}

// UpdateDevice 更新设备
func (Device) UpdateDevice(ctx context.Context, query *dal.Query, record models.Device) error {
	if record.RobotID == "" {
		return errorx.New("设备id不能为空", -1)
	}
	d := dal.Device
	d.WithContext(ctx).Where(d.RobotID.Eq(record.ID)).Updates(&record)
	return nil
}

type DeviceGeoListType struct {
	RobotID          string  `gorm:"robot_id"`
	MerchantPath     string  `gorm:"merchant_path"`
	LatestActiveTime int64   `gorm:"column:latest_active_time"`
	SaleStatus       int     `gorm:"column:sale_status"`
	LocationID       string  `gorm:"column:location_id"`
	FloorName        string  `gorm:"column:floor_name"`
	PositionName     string  `gorm:"position_name"`
	Longitude        float64 `gorm:"column:longitude"`
	Latitude         float64 `gorm:"column:latitude"`
}

// DeviceGeoList 设备的geo信息
func (Device) DeviceGeoList(ctx context.Context, query *dal.Query) (list []*DeviceGeoListType) {
	d := dal.Device
	l := dal.Location
	f := dal.Floor
	p := dal.DevicePosition
	d.WithContext(ctx).
		Join(l, d.LocationID.EqCol(l.ID)).
		Join(f, d.FloorID.EqCol(f.ID)).
		LeftJoin(p, d.PositionID.EqCol(p.ID)).
		Where(d.MerchantID.Gt("1")).
		Group(d.LocationID, d.FloorID, d.RobotID).
		Select(
			d.RobotID, d.MerchantPath, d.LatestActiveTime,
			l.Longitude, l.Latitude,
			l.ID.As("location_id"),
			f.Name.As("floor_name"),
			p.Name.As("position_name"),
		).
		Scan(&list)

	// 全部的设别集合
	var robotIDs []string
	for _, record := range list {
		robotIDs = append(robotIDs, record.RobotID)
	}
	// 获取终端状态
	{
		var cacheStatus map[string]map[string]int
		cacheStatus, _ = Terminal{}.GetCacheStatus(robotIDs)
		if cacheStatus != nil {
			for index, record := range list {
				if cacheStatus[record.RobotID] != nil {
					// 售卖状态，1为售卖中，2为停止售卖
					// 当sale_status为0时，若97在线则为售卖中，否则为停止售卖
					saleStatus := cacheStatus[record.RobotID]["sale_status"]
					if saleStatus == 0 {
						saleStatus = 2
					}
					list[index].SaleStatus = saleStatus
				}
			}
		}
	}
	return list
}
